using SmartCommunity.Models;
using Mapster;
using Microsoft.EntityFrameworkCore;

namespace SmartCommunity.WebApi.Services.System
{
    /// <summary>
    /// 服务类：角色
    /// </summary>
    public class RoleService : BaseService<RoleEntity>
    {
        #region 构造函数
        protected readonly SCDBContext ctx;
        public RoleService(SCDBContext ctx)
        {
            this.ctx = ctx;
        }
        #endregion

        #region 数据查询 
        /// <summary>
        /// 分页查询
        /// </summary>
        public async Task<PageResult<RoleDto>> FindPagedList(RoleQuery roleQuery, Pager pager, LoginUser user)
        {
            if (!user.IsSuperAdmin)
            {
                roleQuery.AddExpression(a => a.RoleCode != AppConstants.SUPER_ADMIN);
            }
            var query = ctx.Roles.AsNoTracking().Where(roleQuery.GetQueryExpression());
            var data = await FindPagedList(query, pager, o => o.OrderByDescending(t => t.CreatedTime));
            return data.Map(o => o.Adapt<RoleDto>());
        }

        /// <summary>
        /// 根据角色ID查询
        /// </summary>
        public async Task<RoleDto> FindRoleById(int roleId)
        {
            var entity = await FindById(roleId);
            return entity.Adapt<RoleDto>();
        }

        /// <summary>
        /// 根据ID查询实体类
        /// </summary>
        private async Task<RoleEntity> FindById(int id)
        {
            return await ctx.Roles.Include(a => a.Menus).SingleOrDefaultAsync(a => a.RoleId == id)
                ?? throw new NotFoundException($"找不到指定的角色,Id:{id}");
        }
        #endregion

        #region 增 删 改
        /// <summary>
        /// 新增角色
        /// </summary>
        public async Task<RoleDto> CreateRole(RoleDto dto, LoginUser user)
        {
            // 新建对象
            var entity = new RoleEntity();
            // 复制属性
            await CopyDtoToEntity(dto, entity, user, true);
            // 执行保存
            ctx.Roles.Add(entity);
            await ctx.SaveChangesAsync();
            // 返回Dto
            return entity.Adapt<RoleDto>();
        }

        /// <summary>
        /// 更新角色
        /// </summary>
        public async Task UpdateRole(RoleDto dto, LoginUser user)
        {
            // 原始数据
            var entity = await FindById(dto.RoleId);
            if (entity.RoleCode != dto.RoleCode)
            {
                throw new MessageException("不允许修改角色编码");
            }
            // 更新字段
            await CopyDtoToEntity(dto, entity, user, false);
            // 执行更新
            await ctx.SaveChangesAsync();
        }

        /// <summary>
        /// 复制dto属性到实体字段
        /// </summary>
        private async Task CopyDtoToEntity(RoleDto dto, RoleEntity entity, LoginUser user, bool isNew)
        {
            if (await ctx.Roles.AnyAsync(a => a.RoleId != dto.RoleId && (a.RoleCode.ToLower() == dto.RoleCode.ToLower() || a.RoleName.ToLower() == dto.RoleName.ToLower())))
            {
                throw new MessageException("当前已存在相同名称或编码的角色");
            }
            entity.RoleCode = dto.RoleCode;
            entity.RoleName = dto.RoleName;
            entity.Remark = dto.Remark;
            entity.Disabled = dto.Disabled;

            entity.Menus = await ctx.Menus.Where(m => dto.MenuIds.Contains(m.MenuId)).ToListAsync();

            // 记录操作人
            if (isNew)
            {
                entity.CreatedBy = user.Username;
                entity.CreatedTime = DateTime.Now;
            }
            entity.UpdatedBy = user.Username;
            entity.UpdatedTime = DateTime.Now;
        }

        /// <summary>
        /// 根据ID删除角色
        /// </summary>
        public async Task DeleteByIds(IEnumerable<int> ids, LoginUser user)
        {
            var lstData = await ctx.Roles.Include(r => r.Users).Include(r => r.Menus).Where(a => ids.Contains(a.RoleId)).ToListAsync();
            if (lstData.Count != ids.Count())
            {
                throw new MessageException("查询出的数据和传入的ID不匹配，请刷新后再试。");
            }
            // 判断是否能删除
            foreach (var entity in lstData)
            {
                if (entity.RoleCode == AppConstants.SUPER_ADMIN)
                {
                    throw new MessageException("不能删除超级管理员角色");
                }
                if (entity.Users.Count != 0)
                {
                    throw new MessageException($"角色{entity.RoleName}存在关联用户，不能删除", MessageType.Warning);
                }
                // 删除菜单关联关系
                entity.Menus.Clear();
                ctx.Roles.Remove(entity);
            }
            // 提交事务
            await ctx.SaveChangesAsync();
        }
        #endregion
    }
}
